﻿#nullable disable
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using NuGet.Protocol;
using Senparc.CO2NET.Cache;
using Senparc.Weixin;
using Senparc.Weixin.TenPay.V3;
using Senparc.Weixin.TenPayV3.Apis;

namespace Web.Areas.miniapp.Controllers
{
    /// <summary>
    /// 小程序支付测试
    /// </summary>
    public class miniapp_payController : BaseController
    {
		#region 变量与属性
		/// <summary>
		/// 上下文HttpContext
		/// </summary>
		private IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
        #endregion

        #region 统一下单
        /// <summary>
        /// 统一下单
        /// 调用支付jsapi缺少参数total_fee,有可能是 此商家的收款功能已被限制，暂无法支付，登录商户后台申请解封，或者查看受到了什么限制
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> GetPrepayid()
        {

			string _xcx_openid = "o00uk7YtXGgoMumstUW3UFy7kZGY";//魏智勇的小程序openid

			try
            {
				//生成订单10位序列号，此处用时间和随机数生成，商户根据自己调整，保证唯一
				var sp_billno = string.Format("{0}{1}{2}", Config.SenparcWeixinSetting.TenPayV3_MchId, SystemTime.Now.ToString("yyyyMMddHHmmss"),
						TenPayV3Util.BuildRandomStr(6));

				var timeStamp = TenPayV3Util.GetTimestamp();
				var nonceStr = TenPayV3Util.GetNoncestr();

				var body = "苹果耳机";
				var price = 100;//支付金额，单位：分

				var notifyUrl = Config.SenparcWeixinSetting.TenPayV3_WxOpenTenpayNotify;

				var basePayApis = new Senparc.Weixin.TenPayV3.Apis.BasePayApis(Config.SenparcWeixinSetting);
				var requestData = new Senparc.Weixin.TenPayV3.Apis.BasePay.TransactionsRequestData(WxOpenAppId, Config.SenparcWeixinSetting.TenPayV3_MchId, body, sp_billno, new Senparc.Weixin.TenPayV3.Entities.TenpayDateTime(SystemTime.Now.AddMinutes(120).DateTime, false), HttpContext.UserHostAddress().ToString(), notifyUrl, null, new() { currency = "CNY", total = price }, new(_xcx_openid), null, null, null);
				var result = await basePayApis.JsApiAsync(requestData);

				WeixinTrace.SendCustomLog("统一订单接口调用结束", "请求：" + requestData.ToJson() + "\r\n\r\n返回结果：" + result.ToJson());
				LogHelper.Info($"统一下单响应结果:{result.ToJson()}", LogHelper.logsSource.名片api, "");
				var packageStr = "prepay_id=" + result.prepay_id;

				//记录到缓存

				var cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();
				cacheStrategy.Set($"WxOpenUnifiedorderRequestData-{_xcx_openid}", requestData, TimeSpan.FromDays(4));//3天内可以发送模板消息
				cacheStrategy.Set($"WxOpenUnifiedorderResultData-{_xcx_openid}", result, TimeSpan.FromDays(4));//3天内可以发送模板消息

				return Json(new
				{
					code = 0,
					msg = "预下单成功，待支付",
					prepay_id = result.prepay_id,
					appId = Config.SenparcWeixinSetting.WxOpenAppId,
					timeStamp,
					nonceStr,
					package = packageStr,
					//signType = "MD5",
					paySign = Senparc.Weixin.TenPay.V3.TenPayV3.GetJsPaySign(WxOpenAppId, timeStamp, nonceStr, packageStr, Config.SenparcWeixinSetting.TenPayV3_Key)
				});

            }
            catch (Exception ex)
            {
                LogHelper.Error($"统一下单异常,openid:{_xcx_openid}", LogHelper.logsSource.名片api, "", ex);
                return Json(new { code = 1, msg = $"预下单失败{ex}"});
            }
        }
        #endregion

        #region 微信支付通知回调地址
        /// <summary>
        /// 微信支付通知回调地址
        /// </summary>
        /// <returns></returns>
        public ActionResult PayNotifyUrl()
        {
            try
            {
                Task.Run(() =>
                {
                    LogHelper.Info("微信支付通知回调", LogHelper.logsSource.名片api);
                });
                #region 解析请求头信息
                var _Headers = HttpContext.Request.Headers;
                string strheader = "";
                foreach (var _header in _Headers)
                {
                    strheader += $"Key:{_header.Key},Value:{_header.Value}";
                }
                Task.Run(() =>
                {
                    LogHelper.Info($"微信支付通知回调Headers:{strheader}", LogHelper.logsSource.名片api);
                });
                #endregion

                #region 无参接口获取请求中的数据流
                string ReqData = "";//请求报文内容
                Stream reqStream = _httpContextAccessor.HttpContext.Request.Body;
                using (StreamReader reader = new StreamReader(reqStream))
                {
                    ReqData = reader.ReadToEndAsync().Result;
                }

                Task.Run(() =>
                {
                    LogHelper.Info($"微信支付通知回调,收到报文{ReqData}", LogHelper.logsSource.名片api);
                });
                #endregion

                JObject _jsonobj = JObject.Parse(ReqData);
                string _returnCode = _jsonobj["returnCode"].Value<string>();//SUCCESS/FAIL 此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断               
                if (_returnCode == "SUCCESS")
                {
                    #region 解析返回的结果
                    string _resultCode = _jsonobj["resultCode"].Value<string>();//业务结果SUCCESS/FAIL
                    //string _openid = _jsonobj["openid"].Value<string>();//用户标识,用户在商户appid下的唯一标识，这个不是小程序的openid
                    string _subOpenid = _jsonobj["subOpenid"].Value<string>();//这个才是小程序的openid
                    //string _tradeType = _jsonobj["tradeType"].Value<string>();//交易类型JSAPI、NATIVE、APP
                    //int _totalFee= _jsonobj["totalFee"].Value<int>();//订单总金额，单位为分
                    string _transactionId = _jsonobj["transactionId"].Value<string>();//微信支付订单号
                    string _outTradeNo = _jsonobj["outTradeNo"].Value<string>();//商户系统内部订单号，要求32个字符内（最少6个字符），只能是数字、大小写字母_-|*且在同一个商户号下唯一。详见商户订单号
                    //string _timeEnd = _jsonobj["timeEnd"].Value<string>();//支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则 
                    #endregion


                    return Json(new { errcode = 1, errmsg = "失败" });
                }
                return Json(new { errcode = 1, errmsg = "失败" });
            }
            catch (Exception ex)
            {
                LogHelper.Error("微信支付通知回调异常", LogHelper.logsSource.名片api, "", ex);
                return Json(new { errcode = 1, errmsg = ex.Message });
            }
        }
        #endregion


    }
}
